<?php

function getApplication($applicationId, $adminId) {
	if (!is_numeric($applicationId)) {
		throw new Exception('Provided applicationId was not a numeric value.');
	} else if (!is_numeric($adminId)) {
		throw new Exception('Provided adminId was not a numeric value.');
	}
	
	$sql = 'SELECT applicationId, applicationName, applicationDescription, package, version, versionString, state FROM applications WHERE applicationId = ' . $applicationId . ' AND adminId = ' . $adminId;
	return mysql_query($sql);
}

  /**
	* Get applications by the admin id and return them in a result set.
	*/
function getApplications($adminId) {
	if (!is_numeric($adminId)) {
		throw new Exception('The given admin id was not a numeric value');
	} else {
		$query = 'SELECT * FROM applications WHERE adminId = ' . $adminId.' AND (state="LIVE" OR state="ERROR")';
		return mysql_query($query);
	}
}

/**
  * Update applications in the database
  */
function updateApplication($applicationId, $applicationName, $applicationDescription) {
	if (!is_numeric($applicationId)) {
		throw new InvalidArgumentException('Provided applicationId was not an integer.');
	} else if (!is_string($applicationName)) {
		throw new InvalidArgumentException('Provided applicationName was not a string.');
	} else if (!is_string($applicationDescription)) {
		throw new InvalidArgumentException('Provided applicationDescription was not a string.');
	} 
	
	$applicationId = (int) $applicationId;
		
	$sql = 'UPDATE applications SET applicationName = "' . $applicationName . '", applicationDescription = "' . $applicationDescription . '" WHERE applicationId = ' . $applicationId;
	$result = mysql_query($sql);
	if(!$result) {
	  return false;
	}
	
	return true;
}

/**
  * Add an administrator to the database. Password is encrypted in this function!
  */
function addAdmin($adminName, $adminMail, $adminPass) {
	$name = mysql_real_escape_string($adminName);
	$mail = mysql_real_escape_string($adminMail);
	$pass = mysql_real_escape_string($adminPass);

	$mailPattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";
	if (!is_string($name)) {
		throw new InvalidArgumentException('Provided adminName was not a string');
	} else if (preg_match($mailPattern, $mail) == 0) {
		throw new InvalidArgumentException('Provided adminMail was not a valid email');
	} else if (!is_string($pass)) {
		throw new InvalidArgumentException('Provided adminPass was not a string');
	}
	
	$pass = md5($pass);
	$sql = 'INSERT INTO admins (adminName, email, `password`, accepted) VALUES ("' . $name . '", "' . $adminMail . '", "' . $adminPass . '", 0)';
	mysql_query($sql);
	/*
		ADD SEND MAIL FUNCTION HERE!!!
	*/
	return mysql_insert_id();
}

/**
  * Edit an administrator name by providing the adminId
  */
function editAdmin($adminId, $adminName, $adminMail, $adminPass = null) {
	if (!is_numeric($adminId)) {
		throw new InvalidArgumentException('Provided adminId was not an integer.');
	} else if (!is_string($adminName)) {
		throw new InvalidArgumentException('Provided adminName was not a string.');
	} else if (!is_string($adminPass) && !is_null($adminPass)) {
		throw new InvalidArgumentException('Provided password was not a string.');
	} else if (!is_string($adminMail)) {
		throw new InvalidArgumentException('Provided mail was not a string.');
	}
	$admin = mysql_real_escape_string($adminName);
	if (!is_null($adminPass)) {
		$password = mysql_real_escape_string(md5($adminPass));
	}
	$mail = mysql_real_escape_string($adminMail);
	
	$sql = "UPDATE admins SET adminName = '$adminName'";
	if (!is_null($adminPass)) {
		$sql .= ", password = '$password'";
	}
	$sql .= ", email='$mail' WHERE adminId = $adminId";
	mysql_query($sql);
}

/**
  * Validate an admin email/password pair.
  * String escaping is done in this function
  * @return The adminId if the administrator is valid, false if not
  */
function validateAdmin($adminMail, $adminPass) {
	$mail = mysql_real_escape_string($adminMail);
	$pass = mysql_real_escape_string($adminPass);
	$mailPattern = '^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$^';
	if (preg_match($mailPattern, $mail)) {
		throw new InvalidArgumentException('provided adminMail was not a valid email.');
	} else if (!is_string($pass)) {
		throw new InvalidArgumentException('provided adminPass was not a string.');
	}
		
	try {
		$sql = 'SELECT adminId FROM admins WHERE email = "' . $mail. '"AND password = "' . md5($pass) . '" AND accepted = 1';
		$rs = mysql_query($sql);
	} catch (Exception $e) {
		return false;
	}

	if (mysql_num_rows($rs) != 1) {
		return false;
	}
	$res = mysql_fetch_assoc($rs);
	
	if ($res['adminId'] != 0) {
		return $res['adminId'];
	}
	return false;
}

  /** Upgrade an inserted admin from pending to accepted
	* Returns true if the update succeeded
	* Returns false if the given input is not numeric
	*/
function acceptAdmin($adminId) {
	if (is_numeric($adminId)) {
		$sql = 'UPDATE admins SET accepted = 1 WHERE adminId = ' . $adminId;
		mysql_query($sql);
		return true;
	}
	return false;
}

  /** Retrieve an admin based on the Id.
	* The resultSet of the query is returned, unless the provided adminId is not a numeric value. In this case, false is returned
	*/
function getAdmin($adminId) {
	if (is_numeric($adminId)) {
		$sql = 'SELECT adminName, email, password FROM admins WHERE adminId = ' . $adminId . ' LIMIT 0, 1';
		return mysql_query($sql);
	}
	return false;
}

  /** Retrieve all errors for a given application
	* Returns all errors in a resultSet
	*/
function getErrors($applicationId) {
	if (!is_numeric($applicationId)) {
		throw new InvalidArgumentException('Given applicationId was not a number');
	} else {
		$sql = 'SELECT * FROM errors WHERE applicationId = ' . $applicationId;
		return mysql_query($sql);
	}
}

  /**
	* Add a new application to the database (pre- postadd)
	* Returns the ID of the inserted application
	*/
function addApplicationPre($name, $description, $adminId) {
	if (!is_string($name)) {
		throw new Exception('Invalid argument name - was not a string.');
	} else if (!is_string($description)) {
		throw new Exception('Invalid argument description - was not a string.');
	} else if (!is_numeric($adminId)) {
		throw new Exception('Invalid argument adminId - was not a numeric value.');
	}
	
	$name = mysql_real_escape_string($name);
	$description = mysql_real_escape_string($description);
	
		
	$query = 'INSERT INTO applications (applicationName, applicationDescription, adminId, package, version, versionString, state) VALUES ("' . $name . '", "' . $description . '", ' . $adminId . ', null, null, null, "ADDING")';
	$res = mysql_query($query);
	if (!$res) {
		throw new Exception(mysql_error() . '<br>' . $query);
	}
	
	$qRes = mysql_query('SELECT LAST_INSERT_ID() as a');
	
	if (!$qRes) 
		throw new Exception('Failed retrieving id of the inserted application.');
	
	$res = mysql_fetch_assoc($qRes);

	return $res['a'];
}

function addApplicationPost($applicationId, $package, $version, $versionString) {
	if (!is_numeric($applicationId)) {
		throw new Exception('Invalid argument applicationId - not a numeric value.');
	} else if (!is_string($package)) {
		throw new Exception('Invalid argument package - not a string.');
	} else if (!is_numeric($version)) {
		throw new Exception('Invalid argument version - not a numeric value.');
	} else if (!is_string($versionString)) {
		throw new Exception('Invalid argument versionString - not a string.');
	}
	
	$package = mysql_real_escape_string($package);
	$versionString = mysql_real_escape_string($versionString);
	
	$query = 'SELECT applicationId FROM applications WHERE package = "' . $package . '" AND version = "' . $version . '"';
	$res = mysql_query($query);
	
	if (mysql_fetch_row($res)) {
		throw new Exception('An application with the package name and version already exists. Please either change your package name or update your version.');
	}
	
	$query = 'UPDATE applications SET package = "' . $package . '", version = ' . $version . ', versionString = "' . $versionString . '", state = "live" WHERE applicationId = ' . $applicationId;

	mysql_query($query);
}

function removeOldPackage($package) {
	if (!is_string($package)) {
		throw new Exception('Invalid argument package - not a string.');
	}
	
	mysql_real_escape_string($package);
	
	$query = 'SELECT applicationId, version FROM applications WHERE package = "' . $package . '" ORDER BY version ASC';
	
	$rs = mysql_query($query);
	
	if (!$rs) {
		throw new Exception('Unable to retrieve list of applications with name ' . $package);
	}
	
	$appArray = null;	
	$maxVersion = 0;
	
	while ($res = mysql_fetch_assoc($rs)) {
		$appArray[$res['applicationId']] = $res['version'];
		if ($res['version'] > $maxVersion) {
			$maxVersion = $res['version'];
		}
	}
	if ($maxVersion != end($appArray)) {
		throw new Exception('Added application package does already exist, and an application with higher version already exists. If you have not added an application with this package name earlier, please change your package name. If the previous application was added by you, please update your version-');
	}
	
	$appId = '';
	if (count($appArray) > 1) {
		foreach ($appArray as $id => $version) {
			if ($version < $maxVersion) {
				$link = 'installs/' . $id . '.apk';
			
				rename($link, $link . '.OLD');
				
				if ($appId != '') {
					$appId .= ' OR ';
				}
				
				$appId .= 'applicationId = ' . $id;
			}
		}

		if ($appId != '') {
			$query = 'UPDATE applications SET state = "OLD" WHERE ' . $appId;
			$rs = mysql_query($query);
			
		
			if (!$rs) 
				throw new Exception('Could not change state of older versions of the application. Please report this incident to an administrator, and attach the contents of this page.<br><br>_functions.php - addAddplicationPost. Attempted SQL:<br>' . var_dump($query));

		} else {
			throw new Exception('No old applications could be overwritten, even the packageName is already in use. There is two possible explanations for this:<br/><ul><li>You are attempting to update your application for the first time. The cause of your error is that another application already uses this package name. The fix is therefore for you to change the package name.</li><li>You are attempting to update an application. You probably forgot to update the version and versionString in the manifest file. Please do so, as GirafPlace relies on these for updating the applications properly</li></ul>');
		}
	}
}

function uploadAPK($id) {
	if ($_FILES["apk"]["error"] > 0 || !isset($_FILES['apk'])) {
		throw new Exception("Return Code: " . $_FILES["apk"]["error"]);
	} else { 
		if (file_exists("installs/". $id . "/" . $_FILES["apk"]["name"])) {
			throw new Exception($_FILES["apk"]["name"] . " already exists. ");
		} else {
			move_uploaded_file($_FILES["apk"]["tmp_name"],"installs/". $id . ".apk");
		}
	}
}

function getInfoFromApk($apkFile,$id) {
	$chw = getcwd();

	chdir("/home/rune/www");

	mkdir("./temp/$id");

	//Get packagename
	$packageArray = explode('"',exec("./aapt l -a installs/$apkFile | grep package"),3);
	$package = $packageArray[1];

	//Get versioncode
	$versioncodeArray = explode(')',exec("./aapt l -a installs/$apkFile | grep versionCode"),3);
	$versioncode = hexdec($versioncodeArray[2]);

	//Get versionname
	$versionnameArray = explode('"',exec("./aapt l -a installs/$apkFile | grep versionName"),3);
	$versionname = $versionnameArray[1];

	//Extract the icon
	exec("unzip ./installs/$apkFile res/drawable-ldpi/icon.png -d ./temp/$id; mv ./temp/$id/res/drawable-ldpi/icon.png /home/rune/www/icos/$id.png");
	
	$settingsZipArray = array(); 
	
	exec("unzip ./installs/$apkFile assets/settings.xml -d ./temp/$id",$settingsZipArray);
	
	if(!strstr($settingsZipArray[1],"inflating"))
		throw new Exception('The package did not contain a settings.xml');

	//Return codes from sw6.xmlvalidator
	define("VALID_XML", 	0);
	define("INVALID_XML", 	1);
	
	//Commands to execute
	$command 	= " ./sw6.xmlvalidator/exec.sh ./temp/$id/assets/settings.xml";
	$command	= escapeshellcmd($command);
	$output 	= array();

	//Execute command and store output and return value
	exec($command, $output, $return);
	
	unlink("./temp/$id/assets/settings.xml");
	rmdir("./temp/$id/assets");
	rmdir("./temp/$id/res/drawable-ldpi");
	rmdir("./temp/$id/res");
	rmdir("./temp/$id");
	chdir($chw);
	
	if(sizeof($output) == 0) {
		return array('package' => $package, 'version' => $versioncode, 'versionString' => $versionname);
	} else {
		Connect();
		foreach($output as $value){
			$query = "INSERT INTO errors (applicationId,errorMessage) VALUES($id,$value)";
			mysql_query($query);
		}
		Close();
		throw new Exception("XML not valid");
	}
}

function cronjobClearing() {
	$query1 = 'SELECT applicationId FROM applications WHERE state = "OLD"';
	$rs = mysql_query($query1);
	
	if ($rs) {
		$delList = '';
		while ($app = mysql_fetch_assoc($rs)) {
			if ($delList == '') {
				$delList .= ' OR';
			}
			$delList .= ' applicationId = ' . $app['applicationId'];
		}
		
		if ($delList != '') {
			$query2 = 'DELETE FROM applicationsabilities WHERE ' . $delList;
			mysql_query($query2);
			
			$query3 = 'DELETE FROM errors WHERE ' . $delList;
			mysql_query($query3);
		
			$query4 = 'DELETE FROM applications WHERE state = "DELETE"';
			mysql_query($query4);
		}
	}	
	//Delete old apk files
	exec("rm installs/*.apk.OLD;");
	
	//Retrieve adding applications
	$query = 'Select applicationId FROM applications WHERE state = "ADDING"';
	$res = mysql_query($query);
	while ($rs = mysql_fetch_assoc($res)) {
		exec('rm installs/' . $rs['applicationId'].  '.apk');
	}
}

  /**
	* Sets abilities of the provided application id.
	* Old abilities are ignored (kept for compatibility)
*/
function setAbilities($application, $abilities, $oldAbilities = null) {
	if (is_array($abilities) && is_numeric($application)) {
		if (count($abilities) != 0) {
			for ($i = 1; $i <= 11; $i++) {
				switch ($i) {
					case 1:
						$s .= ' canDragAndDrop = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 2:
						$s .= ', canHear = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 3:
						$s .= ', requiresSimpleVisualEffects = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 4:
						$s .= ', canAnalogTime = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 5:
						$s .= ', canDigitalTime = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 6:
						$s .= ', canRead = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 7:
						$s .= ', hasBadVision = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 8:
						$s .= ', requiresLargeButtons = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 9:
						$s .= ', canSpeak = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 10:
						$s .= ', canNumbers = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					case 11:
						$s .= ', canUseKeyboard = ';
						$s .= (isset($abilities[$i])) ? '1' : '0';
						break;
					default:
						break;
				}
			}
			$sql = 'UPDATE applications set ' . $s . ' WHERE applicationId = ' . $application;
			mysql_query($sql);
		}
	}
}

function insertError($applicationId, $errorMessage) {
	if (!is_numeric($applicationId)) {
		throw new Exception('Invalid argument applicationId - not a numeric value.');
	} else if (!is_string($errorMessage)) {
		throw new Exception('Invalid argument errorMessage - not a string.');
	}
	
	$eM = mysql_real_escape_string($errorMessage);
	
	$query = 'INSERT INTO errors (applicationId, errorMessage) VALUES(' . $applicationId . ', "'.$eM . '")';
	mysql_query($query);
}
